package com.freework.freedbm.dao;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import com.freework.Cfg;
import com.freework.freedbm.base.BaseDTO;
import com.freework.freedbm.base.DTO;
import com.freework.freedbm.base.ProtoQueryDAO;
import com.freework.freedbm.cfg.fieldcfg.FieldInfo;
import com.freework.freedbm.cfg.fieldcfg.FieldInfoEnum;
import com.freework.freedbm.cfg.tablecfg.TableCfg;
import com.freework.freedbm.cfg.tablecfg.TableQuery;
import com.freework.freedbm.dao.jdbcm.JdbcForDTO;
import com.freework.freedbm.dao.jdbcm.Param;
import com.freework.freedbm.dao.jdbcm.QueryInfo;
import com.freework.freedbm.dao.jdbcm.QueryManager;
import com.freework.freedbm.util.DTOByCfg;
import com.freework.util.SqlUtil;

public class DefaultProtoQueryDAO extends AbstractDAO implements
		ProtoQueryDAO<DTO, FieldInfoEnum> {
	protected QueryManager jm = QueryManager.getJdbcManager();
	private final static DefaultProtoQueryDAO dfaultQueryDAO = new DefaultProtoQueryDAO();

	private DefaultProtoQueryDAO() {

	}

	public static DefaultProtoQueryDAO getDefaultQueryDAO() {
		return dfaultQueryDAO;
	}

	public DTO getObject(Connection con, DTO key)
			throws SQLException {
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(key);
		JdbcForDTO[] ufieldInfos = tablecfg.getPKey();

		QueryInfo qi = QueryInfo.getQueryInfo(tablecfg, getWhere(ufieldInfos), getParams(
						ufieldInfos, key));

		return (DTO) jm.getDTOObject(con, qi);
	}

	
	public String getWhere(JdbcForDTO[] ufieldInfos,String where){
		String mywhere=getWhere(ufieldInfos);
		if(where!=null&&!where.equals("")){
			if(mywhere!=null&&!mywhere.equals("")){
				
				mywhere=mywhere+" and "+where;
				
				
			}else{
				mywhere=where;
			}
			
		}
		return mywhere;
	}
	
	public List<DTO> query(Connection con, DTO dto,String where)
			throws SQLException {
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		
		QueryInfo qi = QueryInfo.getQueryInfo(tablecfg, getWhere(ufieldInfos,where), getParams(
						ufieldInfos, dto));
		qi.setJdbcForDTOs(tablecfg.getFields());
		System.out.println(qi.getQuerySelect());
		return query(con, qi);
	}

	public TotalResult<DTO> queryPage(Connection con, int start,
			int limit, DTO dto,String where) throws SQLException {
		TotalResult<DTO> tr = new TotalResult<DTO>();
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		String querySelect = tablecfg.getQuerysql();
		 where = getWhere(ufieldInfos,where);
		if (!where.equals(""))
			querySelect = querySelect + " where " +where;
		List<Param> params = Arrays.asList(this.getParams(ufieldInfos, dto));
		QueryInfo qi = new QueryInfo(tablecfg);
		qi.setDto(dto);
		qi.setJdbcForDTOs(tablecfg.getFields());
		qi.setStart(start);
		qi.setLimit(limit);
		qi.setQuerySelect(querySelect);
		qi.setParams(params);
		tr.setItems(query(con, qi));

		QueryInfo count = new QueryInfo();
		count
				.setJdbcForDTOs(new JdbcForDTO[] { new JdbcForObject(
						Cfg.Integer) });
		count.setQuerySelect(SqlUtil.getCountSQL(querySelect));
		count.setParams(params);
		tr.setResults(((Integer) jm.getObject(con, count)).intValue());
		return tr;
	}

	JdbcForDTO[] fieldInfoEnumsToFielders(FieldInfoEnum fieldInfoEnums[]) {
		JdbcForDTO[] fieldInfos = new FieldInfo[fieldInfoEnums.length];
		for (int i = 0; i < fieldInfoEnums.length; i++) {
			fieldInfos[i] = fieldInfoEnums[i].getFieldInfo();
		}
		return fieldInfos;

	}
	public TotalResult<DTO> queryPage(Connection con, int start,
			int limit, DTO dto,String where, JdbcForDTO... e) throws SQLException {
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		String querySelect = Cfg.DB_TYPE.getQuerySql(tablecfg.getTableName(), e, getWhere(ufieldInfos,where));
		List<Param> params = Arrays.asList(this.getParams(ufieldInfos, dto));

		QueryInfo qi = new QueryInfo(tablecfg);

		qi.setDto(dto);
		qi.setJdbcForDTOs(e);
		qi.setStart(start);
		qi.setLimit(limit);
		qi.setQuerySelect(querySelect);
		qi.setParams(params);
		TotalResult t = new TotalResult();
		t.setItems(query(con, qi));

		QueryInfo count = new QueryInfo();
		count
				.setJdbcForDTOs(new JdbcForDTO[] { new JdbcForObject(
						Cfg.Integer) });
		count.setQuerySelect(SqlUtil.getCountSQL(querySelect));
		count.setParams(params);
		t.setResults(((Integer) jm.getObject(con, count)).intValue());

		return t;
	}
	
	public TotalResult<DTO> queryPage(Connection con, int start,
			int limit, DTO dto,String where, FieldInfoEnum... e) throws SQLException {
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		String querySelect = Cfg.DB_TYPE.getQuerySql(tablecfg.getTableName(), e, getWhere(ufieldInfos,where));
		List<Param> params = Arrays.asList(this.getParams(ufieldInfos, dto));

		QueryInfo qi = new QueryInfo(tablecfg);

		qi.setDto(dto);
		qi.setJdbcForDTOs(fieldInfoEnumsToFielders(e));
		qi.setStart(start);
		qi.setLimit(limit);
		qi.setQuerySelect(querySelect);
		qi.setParams(params);
		TotalResult t = new TotalResult();
		t.setItems(query(con, qi));

		QueryInfo count = new QueryInfo();
		count
				.setJdbcForDTOs(new JdbcForDTO[] { new JdbcForObject(
						Cfg.Integer) });
		count.setQuerySelect(SqlUtil.getCountSQL(querySelect));
		count.setParams(params);
		t.setResults(((Integer) jm.getObject(con, count)).intValue());

		return t;
	}

	public List<DTO> query(Connection con, QueryInfo qi)
			throws SQLException {
		return jm.query(con, qi);
	}

	public DTO getDTOObject(Connection con, QueryInfo qi)
			throws SQLException {

		return (DTO) jm.getDTOObject(con, qi);
	}

	public Object getObject(Connection con, QueryInfo qi) throws SQLException {

		return jm.getObject(con, qi);
	}

	public List<DTO> query(Connection con, DTO dto, String where,
			FieldInfoEnum... e) throws SQLException {
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		String querySelect = TableCfg.DB_TYPE.getQuerySql(tablecfg
				.getTableName(), e, getWhere(ufieldInfos,where));
		List<Param> params = Arrays.asList(this.getParams(ufieldInfos, dto));
		QueryInfo qi = new QueryInfo( DTOByCfg.getTableDataManager(dto));
		qi.setDto(dto);
		qi.setJdbcForDTOs(fieldInfoEnumsToFielders(e));
		qi.setQuerySelect(querySelect);
		qi.setParams(params);

		return query(con, qi);
	}
	public List<DTO> query(Connection con, DTO dto, String where,
			JdbcForDTO... e) throws SQLException {
		TableQuery tablecfg =  DTOByCfg.getTableDataManager(dto);
		JdbcForDTO[] ufieldInfos = DTOByCfg.getUpdateField(dto,true);
		String querySelect = TableCfg.DB_TYPE.getQuerySql(tablecfg
				.getTableName(), e, getWhere(ufieldInfos,where));
		List<Param> params = Arrays.asList(this.getParams(ufieldInfos, dto));
		QueryInfo qi = new QueryInfo( DTOByCfg.getTableDataManager(dto));
		qi.setDto(dto);
		qi.setJdbcForDTOs(e);
		qi.setQuerySelect(querySelect);
		qi.setParams(params);
		return query(con, qi);
	}
	public List<DTO> query(Connection con, DTO dto)
			throws SQLException {
		return this.query(con, dto, "");
	}

	public List<DTO> query(Connection con, DTO dto,
			FieldInfoEnum... e) throws SQLException {
		// TODO Auto-generated method stub
		return this.query(con, dto, null, e);
	}

	public TotalResult<DTO> queryPage(Connection con, int start,
			int limit, DTO dto) throws SQLException {
		// TODO Auto-generated method stub
		return this.queryPage(con, start, limit, dto, "");
	}

	public TotalResult<DTO> queryPage(Connection con, int start,
			int limit, DTO dto, FieldInfoEnum... e) throws SQLException {
		// TODO Auto-generated method stub
		return this.queryPage(con, start, limit, dto, null, e);
	}

	
}
